#include "basic_types.h"
#include "stm32_os_list.h"
#include "shellCmd.h"

#define MAXCMDLEN 128
static char cmdbuff[MAXCMDLEN];
static char shellcmd[MAXCMDLEN];
static int cmdbuffIndex = 0;
int haveShellCmd = 0;
void printAllcmd();
void shellUart(uint8 chr)
{	
	if(cmdbuffIndex >= MAXCMDLEN)
	{
		memset(cmdbuff, '\0', MAXCMDLEN);
		cmdbuffIndex = 0;
	}
	if(chr == '\r')
	{
		sprintf(shellcmd, "%s", cmdbuff);
		memset(cmdbuff, '\0', cmdbuffIndex);
		haveShellCmd = 1;
		cmdbuffIndex = 0;
	}else
		cmdbuff[cmdbuffIndex++] = chr;
}
static bool initflag = 0;
static struct stm32_list_head cmdlist;

char argv[10][MAXCMDLEN] = {0};
void runShell()
{
	memset(argv, 0, sizeof(argv));
	int argc = 0;
	char *p = shellcmd;
	
	int offset=0;
	int isSpace;
	while(*p)
	{
		if(*p != ' ')
		{
			isSpace = 0;
			argv[argc][offset++] = *p;
		}
		else
		{
			if(!isSpace){
				argc++;
				offset=0;
				isSpace = 1;
			}
		}
		p++;
	}
	char **scargv = (char**)malloc(sizeof(char*) * (argc+1));
	for(int i=0; i<argc+1; i++)
	{		
		scargv[i] = (char*)&argv[i];
	}
	struct stm32_list_head *pos, *n;
	stm32_list_for_each_safe(pos, n, &cmdlist)
	{
		SHELL_CMD* sc = stm32_list_entry(pos, SHELL_CMD, head);
		if(sc->match(argv[0]))
		{
			sc->run(argc+1, scargv);
			free(scargv);
			return;
		}
	}
	free(scargv);
	printAllcmd();
	
}
void printAllcmd()
{
	struct stm32_list_head *pos, *n;
		stm32_list_for_each_safe(pos, n, &cmdlist)
	{
		SHELL_CMD* sc = stm32_list_entry(pos, SHELL_CMD, head);
		if(!sc->match("help"))
		{
			sc->help();
		}
	}
}

void registCmd(SHELL_CMD *sc)
{
	if(!initflag)
	{
		initflag = 1;
		stm32_list_create(&cmdlist);
	}
	stm32_list_add(&sc->head, &cmdlist);
}

extern SHELL_CMD s_help;
extern SHELL_CMD s_system;
extern SHELL_CMD s_osd;

bool matchCmd(char *cmd, char *fullCmd)
{
	return strlen(cmd)<=strlen(fullCmd)
			&& strncmp(cmd, fullCmd, strlen(cmd))==0;
}
void init_shell()
{
	registCmd(&s_help);
	registCmd(&s_system);
	registCmd(&s_osd);
}
